#include"myheadd.h"



Friend *init_list(void)
{
    Friend *head = malloc(sizeof(Friend));
    if (head != NULL)
    {
        INIT_LIST_HEAD(&head->list);
    }
    return head;
}

// 新建节点
Friend *new_friend(char *user_name, char *ip, unsigned short port,unsigned short private_port,unsigned short file_port)
{
    Friend *new = malloc(sizeof(Friend));
    if (new != NULL)
    {
        strcpy(new->user_name, user_name);
        strcpy(new->user_qm, "暂无个性签名");
        strcpy(new->ip, ip);
        new->port = port;
        new->private_port = private_port;
        new->file_port = file_port;
        INIT_LIST_HEAD(&new->list);
    }

    return new;
}

//查找节点
bool find_friend(char *user_name)
{
    Friend *tmp = NULL;
    list_for_each_entry(tmp,&friend_list->list,list)
    {
        if(strcmp(tmp->user_name,user_name) == 0)
            return true;
    }
    return false;
}

void show_friend_list(void)
{
    pthread_mutex_lock(&list_mutex);
    Friend *tmp = NULL;
    printf("用户名\t IP地址\t 端口号\n");
    list_for_each_entry(tmp, &friend_list->list, list)
    {
        printf("%s\t %s\t %hu\n", tmp->user_name, tmp->ip, tmp->port);
    }
    pthread_mutex_unlock(&list_mutex);
}

//发送广播
void *send_broadcast(void *arg)
{
    
    char *user_name = (char *)arg;
    //创建udp套接字
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);

    //允许发送广播
    int on = 1;
    setsockopt(sockfd,SOL_SOCKET,SO_BROADCAST,&on,sizeof on);

    struct sockaddr_in addr;
    addr.sin_family = AF_INET;                      // 地址族
    addr.sin_port = htons(54321);           // 端口
    addr.sin_addr.s_addr = inet_addr("192.168.4.255");      // 广播地址

    //发送数据
    char send_buf[100]={0};
    sprintf(send_buf,"%s:0:%hu:%hu",user_name,my_private_port,my_file_port);//第一次是看上下线，第二次是拼接不一样的端口,第三次拼接文件端口
    while (1)
    {
        sendto(sockfd,send_buf, strlen(send_buf), 0, (struct sockaddr *)&addr, sizeof(addr));
        sleep(1);
    }
}


void *recv_broadcast(void *arg)// 接收广播
{
    char *self_name = (char *)arg;
   
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0); // 创建udp套接字

    int on = 1;
    setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));

    struct sockaddr_in recv_addr,send_addr;
    recv_addr.sin_family = AF_INET;                    // 地址族
    recv_addr.sin_port = htons(54321);                 // 端口
    recv_addr.sin_addr.s_addr = htonl(INADDR_ANY);     // IPV4 地址
    if (bind(sockfd, (struct sockaddr *)&recv_addr, sizeof(recv_addr)) < 0)
    {
        perror("bind() error\n");
        return NULL;
    }

    // 接收数据
    char msg[100] = {0};
    socklen_t len = sizeof(send_addr);
    
    //Friend *new = NULL;
    while (1)
    {
       
        bzero(msg, sizeof(msg));

        recvfrom(sockfd, msg, sizeof(msg), 0, (struct sockaddr *)&send_addr, &len);
        
        //解析 0上线 1下线
       // 修改 radio.c 中 recv_broadcast 的解析部分
        char *user_name = strtok(msg, ":");
        char *status_str = strtok(NULL, ":");
        
        if (user_name == NULL || status_str == NULL) 
        {
            continue; // 忽略格式错误的消息
        }

        int status = atoi(status_str);
       
        if (status == 0)
        {
            char *private_port_str = strtok(NULL, ":");//拆端口
             char *file_port_str = strtok(NULL, ":");//加了一个文件端口
              unsigned short private_port = atoi(private_port_str);  // 8000
            unsigned short file_port = atoi(file_port_str);       
            if (private_port_str == NULL || file_port_str == NULL) 
            {
                   continue; // 格式错误，忽略
         
            }
            pthread_mutex_lock(&list_mutex); 
            if (find_friend(user_name))
            {
                pthread_mutex_unlock(&list_mutex); 
                continue;
            }
            
            Friend *new = new_friend(user_name, inet_ntoa(send_addr.sin_addr), ntohs(send_addr.sin_port),private_port,file_port);
            new->is_offline=0;
            list_add_tail(&new->list, &friend_list->list);
            pthread_mutex_unlock(&list_mutex);
            printf("%s 上线了\n", user_name);
        } // 上线

        else if(status == 1)
        {
             pthread_mutex_lock(&list_mutex);
            Friend *new = NULL;
            list_for_each_entry(new, &friend_list->list, list)
            {
                if(strcmp(new->user_name,user_name) == 0)
                {
                    list_del(&new->list);
                    free(new);
                    printf("%s 下线了\n", user_name);
                    break;
                }
        
            }
            pthread_mutex_unlock(&list_mutex);
        }

        //修改自己的资料
        else if (status == 2)
        {
            // 解析个性签名
            char *signature = strtok(NULL, ":");
            if (signature == NULL)
            {
                continue; // 格式错误，忽略
            }

            pthread_mutex_lock(&list_mutex);
            Friend *existing = NULL;
            list_for_each_entry(existing, &friend_list->list, list)
            {
                if (strcmp(existing->user_name, user_name) == 0)
                {
                    // 更新个性签名
                    strncpy(existing->user_qm, signature, sizeof(existing->user_qm) - 1);
                    printf("%s 更新了个性签名: %s\n", user_name, signature);
                    break;
                }
            }
            pthread_mutex_unlock(&list_mutex);
        }

        //修改自己的资料
    }
}

//发送下线广播（单独函数，退出前调用）
void send_offline_msg(char *user_name)
{
    int sock_fd=socket(AF_INET,SOCK_DGRAM,0);

    int on=1;
    setsockopt(sock_fd,SOL_SOCKET,SO_BROADCAST,&on,sizeof (on));

    struct sockaddr_in addr;
    addr.sin_family=AF_INET;
    addr.sin_port=htons(54321);
    addr.sin_addr.s_addr=inet_addr("192.168.4.255");
     
    //发送下线消息：“用户名:1”
    char send_buf[100]={0};
    sprintf(send_buf,"%s:1",user_name);
    sendto(sock_fd,send_buf,strlen(send_buf),0,(struct sockaddr *)&addr,sizeof(addr));
    close(sock_fd);
}

